#include "Array.hpp"
#include "Debug.hpp"
#include "Solver.hpp"
#include "Types.hpp"
#include <string>
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
#include <fstream>
#include<stdio.h>
#include <sys/time.h>
#define PI 3.14159265

double timeStamp();

int main(int argc, char *argv[])
{
    if (argc !=3)
    {
        ERROR("Please enter the number of levels and cycles\n ./mgsolve N_levels N_cycles\n Program exiting...\n"); // Valid even if the Debug mode is Off.
        return 1;
    }
    //Parse the parameters
    size_t levels = atoi(argv[1])+1;
    size_t cycles = atoi(argv[2]);
    //Construct the solver
    Solver mgSolver=Solver(levels);
    //The dimension of the problem must be equivalent to the one set it up in the solver finest grid. Array(levels-1)
    Array lhs(levels-1);
    Array rhs(levels-1);

    //Initialize the grids
    lhs.fill(0.0);
    rhs.fill(0.0);
    // Boundary conditions
    auto bound_func= [](const real& x,const real& y) ->real {return sin(PI*x)*sinh(PI*y);};
    lhs.setAllDirichletBoundary(bound_func);
    //Solve the problem
    std::cout<<BLUE<<"SOLVING THE PROBLEM ...\n"<<WHITE;
    real t2,t1=timeStamp();
    mgSolver.mgSolve(lhs,rhs,cycles,3,3);
    t2=timeStamp();
    std::cout<<"Computation time[s]: "<<t2-t1<<"\n";
    //Print solution
    std::ofstream out("solution.txt");
    lhs.printGNUPLOT(out);
    out.close();
    std::cout<<"DONE\n";
    return 0;
}


double timeStamp()
{
    struct timeval tp;
    gettimeofday(&tp, NULL);
    return((double)(tp.tv_sec + tp.tv_usec/1000000.0));
}
